﻿using System;
using System.Drawing;
using System.IO;
using System.IO.Pipes;
using System.Runtime.InteropServices;

namespace QAQ
{
    class MouseCtrl
    {
        private StreamWriter MousePosPipeSW;

        public MouseCtrl()
        {
            var npipe = new NamedPipeClientStream(".", "mGetCursorPosServerPipe0", PipeDirection.Out);
            npipe.Connect();
            MousePosPipeSW = new StreamWriter(npipe);
            MousePosPipeSW.AutoFlush = true;
        }

        private bool l = false;
        private int lx;
        private int ly;
        public void Lock()
        {
            if (false==l)
            {
                Point lpPoint;
                USER32.GetCursorPos(out lpPoint);
                lx = lpPoint.X;
                ly = lpPoint.Y;
                l = true;
            }
            MousePosPipeSW.Write(string.Format("set {0} {1}", (int)(lx), (int)(ly)));
        }
        public void Move(int x, int y)
        {
            int mx = 0, my = 0;
            //sendpos to the dx server

            //User32.PostMessage(hwnd, WMsg.WM_MOUSEMOVE, IntPtr.Zero, IntPtr.Zero);
            MousePosPipeSW.Write(string.Format("set {0} {1}", (int)(mx + x), (int)(my + y)));
            //only for gc, need to inform the window

            //System.Windows.Forms.Cursor.Position = new System.Drawing.Point((mx + x), (my + y));
        }
        public void MoveRelatedToProcess(IntPtr hwnd, int x, int y)
        {
            int mx = 0, my = 0;
            GetWindowPos(hwnd, ref mx, ref my);
            //sendpos to the dx server

            //User32.PostMessage(hwnd, WMsg.WM_MOUSEMOVE, IntPtr.Zero, IntPtr.Zero);
            MousePosPipeSW.Write(string.Format("set {0} {1}", (int)(mx + x), (int)(my + y)));
            //only for gc, need to inform the window
            
            //System.Windows.Forms.Cursor.Position = new System.Drawing.Point((mx + x), (my + y));
        }
        private static IntPtr CreateLParam(int LoWord, int HiWord)
        {
            return (IntPtr)((HiWord << 16) | (LoWord & 0xffff));
        }

        public void Release()
        {
            MousePosPipeSW.Write("clr");
            l = false;
        }
        private void GetWindowPos(IntPtr hWnd, ref int x, ref int y)
        {
            if (hWnd == IntPtr.Zero)
            {
                return;
            }
            IntPtr hWndParent = USER32.GetParent(hWnd);
            Rectangle rect = new Rectangle();

            USER32.MapWindowPoints(hWnd, hWndParent, ref rect, 1);
            var point = rect.Location;
            x = point.X;
            y = point.Y;
        }

        private class USER32
        {
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool GetCursorPos(out System.Drawing.Point lpPoint);
            // Or use System.Drawing.Point (Forms only)
            [DllImport("user32.dll")]
            public static extern IntPtr FindWindow(String sClassName, String sAppName);
            [DllImport("user32", ExactSpelling = true, SetLastError = true)]
            internal static extern int MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, [In, Out] ref Rectangle rect, [MarshalAs(UnmanagedType.U4)] int cPoints);
            [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
            public static extern IntPtr GetParent(IntPtr hWnd);
        }
    }
}
